/*Slide 41 in  Introduction to Parallel I/O
 * Best practices slides 50-52
 *
 * Jumpshot and MPE tools
 * http://www.mcs.anl.gov/perfvis
 TAU
 * http://www.cs.uoregon.edu/research/tau/home.php
 Intel Trace Analyzer and Collector (formerly Pallas Vampir)
 * http://www.intel.com/cd/software/products/asmo-na/eng/cluster/tanalyzer/index.htm
 Paradyn
 * http://www.cs.wisc.edu/~paradyn
 Pablo
 * http://www.renci.org/software/
 Many other vendor tools exist
 * e.g., xmpi (SGI and HP)
 *
 * Reads matrix in DCSC format using struct Item
 * IR and NUM are interleaved
 * IR_i1,NUM_i1,IR_i2,NUM_i2,...,IR_in,NUM_i3
 *
 * */
#include <stdlib.h>
#include <stdio.h>
#include "mpi.h"
#include "mpi_helper.h"
#include "fileparser.cpp"

using namespace std;

typedef struct {
	int i;
	float w;
} Item ;

int main(int argc, char* argv[]) {
	int np, myid;
	int JC_count, CP_count, IR_count, NUM_count;
	MPI_Offset offset;
	MPI_File myfile; /* Shared file */
	MPI_Status status; /* Status returned from read */

	/* Initialize MPI */
	MPI_Init(&argc, &argv);
	MPI_Comm_rank(MPI_COMM_WORLD, &myid);
	MPI_Comm_size(MPI_COMM_WORLD, &np);

	/* Open the file */
	MPI_File_open(MPI_COMM_WORLD, "dcsc_mat2.bin", MPI_MODE_RDONLY,
			MPI_INFO_NULL, &myfile);
	int * header = (int*) malloc(4 * sizeof(int));
	MPI_File_read(myfile, header, 4, MPI_INT, &status);
	JC_count = header[0];
	CP_count = header[1];
	IR_count = header[2];
	NUM_count = header[3];

	int JC_CP[JC_count + CP_count];
	MPI_File_get_position(myfile, &offset);
	MPI_File_read(myfile, &JC_CP, JC_count + CP_count, MPI_INT,
			&status);
	MPI_File_get_position(myfile, &offset);
	printf("curr offset %d\n", offset);
	/*for (int i = 0; i < JC_count + CP_count; i++)
	 printf("val : %d,  ", JC_CP[i]);
	 printf("\n", "");*/
	int * ir_buf;
	float * num_buf;

	MPI_Datatype Itemtype;
	MPI_Datatype types[2] = {MPI_INT, MPI_FLOAT};
	int blocklen[2] = {1,1};
	MPI_Aint disp[2], base;
	Item item;
	printf("item size: %d", (int)sizeof(item));

	MPI_Get_address(&item, &base);
	MPI_Get_address(&item.i, &disp[0]);
	MPI_Get_address(&item.w, &disp[1]);
	disp[0] = disp[0] - base;
	disp[1] = disp[1] - base;


	MPI_Type_struct(2, blocklen, disp, types, &Itemtype);
	MPI_Type_commit(&Itemtype);

	for (int i = 0; i < JC_count; i++) {
		int ir_start = JC_CP[JC_count + i];
		int ir_end = JC_CP[JC_count + i + 1];
		int buflen = (ir_end - ir_start);
		printf("buflen: %d\n", buflen);
		Item * items = (Item*)malloc(sizeof(Item) * buflen);

		MPI_File_read(myfile, items, buflen, Itemtype, &status);
		//printf("curr offset %d\n", offset);
		for (int i = 0; i < buflen; i++)
			cerr << items[i].i << ":" << items[i].w << endl;
	}

	/*int start = myid % JC_count;
	 MPI_File_get_position(myfile, &offset);

	 int j;
	 MPI_File_read_at(myfile, offset + start * sizeof(int), &j, 1, MPI_INT,
	 &status);
	 printf("J : %d\n", j);
	 int * nzc = (int*) malloc(2 * sizeof(int));
	 MPI_File_read_at(myfile, offset + ((start + JC_count) * sizeof(int)), nzc,
	 2, MPI_INT, &status);
	 printf("NZC %d\n", nzc[1] - nzc[0]);
	 int * IR = (int*) malloc(nzc[1] - nzc[0] * sizeof(int));
	 MPI_File_read_at(myfile,
	 offset + ((start + JC_count + CP_count) * sizeof(int)), IR,
	 nzc[1] - nzc[0], MPI_INT, &status);

	 for (int i = 0; i < nzc[1] - nzc[0]; i++) {
	 printf("IR at %d: %d\n", i, IR[i]);
	 }
	 float * NUM = (float*) malloc((nzc[1] - nzc[0]) * sizeof(float));
	 MPI_File_read_at(myfile,
	 offset + ((start + JC_count + CP_count + IR_count) * sizeof(int)),
	 NUM, nzc[1] - nzc[0], MPI_FLOAT, &status);
	 for (int i = 0; i < (nzc[1] - nzc[0]); i++) {
	 printf("NUM at %d: %.4f\n", i, NUM[i]);
	 }
	 */
	/* Close the file */
	MPI_File_close(&myfile);

	MPI_Finalize();
	exit(0);
}
